Introduction

Welcome to the SIB Days 2020 - virtual conference Spatial Transcriptomics workshop by 10x genomics!

10x Home

The purpose of this tutorial will be to walk users through some of the steps necessary to explore data produced by the 10x Genomics Visium Spatail Gene Expression Solution and the Spaceranger pipeline. We will investigate the datasets whith are all freely available from 10x Genomics.

Seurat Tutorial

Things to know about this workshop

  1. All files that will be used can be found at: /mnt/libs/shared_data/
  2. Getting started with R and Visium data outside of Seurat at: https://support.10xgenomics.com/spatial-gene-expression/software/pipelines/latest/rkit
  3. Reference genome for all samples is GRCh38/mm10
  4. All 10x software including Spaceranger, and Loupe Browser, can be downloaded from the 10x Support Site

Exploring Visium Data with Seurat

Load our packages

library(Seurat)
library(ggplot2)
library(patchwork)
library(dplyr)
library(RColorBrewer)

Loading data in a Seurat object

Real Dataset for the tutorial

mouse_brain_sa <- Load10X_Spatial(data.dir = "/mnt/libs/shared_data/mouse_brain_sa/outs/",
                filename = "V1_Mouse_Brain_Sagittal_Anterior_filtered_feature_bc_matrix.h5")

Same data just internal to 10x

mouse_brain_sa <- Load10X_Spatial(data.dir = "/mnt/analysis/marsoc/pipestances/HMKLFDMXX/SPATIAL_RNA_COUNTER_PD/160121/HEAD/outs/")

There are a bunch of datasets hoted by the Satija lab in the Seurat Data Package.

Results

QC

Let’s have a look at some basic QC information. Keep in mind that most seurat plots are ggplot object and can be manipulated as such.

Counts = UMI Features = Genes

plot1 <- VlnPlot(mouse_brain_sa, features = "nCount_Spatial", pt.size = 0.1) + 
  ggtitle("UMI") +
  theme(axis.text.x = element_blank(), 
        axis.title.x = element_blank(), 
        legend.position = "right") +
  NoLegend()

plot2 <- VlnPlot(mouse_brain_sa, features = "nFeature_Spatial", pt.size = 0.1) + 
  ggtitle("Genes") +
  theme(axis.text.x = element_blank(), 
        axis.title.x = element_blank(), 
        legend.position = "right") +
  NoLegend()

plot3 <- SpatialFeaturePlot(mouse_brain_sa, features = "nCount_Spatial") + 
  theme(legend.position = "right")

plot4 <- SpatialFeaturePlot(mouse_brain_sa, features = "nFeature_Spatial") +
  theme(legend.position = "right")

plot1 + plot2 + plot3 + plot4 + plot_layout(nrow = 2, ncol = 2)

Normilization

Spaceranger does normiliaztion for clustering and DE but does not return that normalized matrix

Pre-normalization Raw UMI counts

SpatialFeaturePlot(mouse_brain_sa, features = c("Hpca", "Ttr"))

SE transform

Don’t worry about reachediteration limit warnings. See https://github.com/ChristophH/sctransform/issues/25 for discussion

Default assay will now be set to SCT

mouse_brain_sa <- SCTransform(mouse_brain_sa, assay = "Spatial", verbose = TRUE)
Calculating cell attributes for input UMI matrix
Variance stabilizing transformation of count matrix of size 17667 by 2696
Model formula is y ~ log_umi
Get Negative Binomial regression parameters per gene
Using 2000 genes, 2696 cells

  |                                                                                                                                
  |                                                                                                                          |   0%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |===============                                                                                                           |  12%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |==============================                                                                                            |  25%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |==============================================                                                                            |  38%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |=============================================================                                                             |  50%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |============================================================================                                              |  62%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |============================================================================================                              |  75%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |===========================================================================================================               |  88%
iteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reachediteration limit reached

  |                                                                                                                                
  |==========================================================================================================================| 100%
Second step: Get residuals using fitted parameters for 17667 genes

  |                                                                                                                                
  |                                                                                                                          |   0%
  |                                                                                                                                
  |==                                                                                                                        |   1%
  |                                                                                                                                
  |===                                                                                                                       |   3%
  |                                                                                                                                
  |=====                                                                                                                     |   4%
  |                                                                                                                                
  |=======                                                                                                                   |   6%
  |                                                                                                                                
  |=========                                                                                                                 |   7%
  |                                                                                                                                
  |==========                                                                                                                |   9%
  |                                                                                                                                
  |============                                                                                                              |  10%
  |                                                                                                                                
  |==============                                                                                                            |  11%
  |                                                                                                                                
  |================                                                                                                          |  13%
  |                                                                                                                                
  |=================                                                                                                         |  14%
  |                                                                                                                                
  |===================                                                                                                       |  16%
  |                                                                                                                                
  |=====================                                                                                                     |  17%
  |                                                                                                                                
  |=======================                                                                                                   |  19%
  |                                                                                                                                
  |========================                                                                                                  |  20%
  |                                                                                                                                
  |==========================                                                                                                |  21%
  |                                                                                                                                
  |============================                                                                                              |  23%
  |                                                                                                                                
  |==============================                                                                                            |  24%
  |                                                                                                                                
  |===============================                                                                                           |  26%
  |                                                                                                                                
  |=================================                                                                                         |  27%
  |                                                                                                                                
  |===================================                                                                                       |  29%
  |                                                                                                                                
  |=====================================                                                                                     |  30%
  |                                                                                                                                
  |======================================                                                                                    |  31%
  |                                                                                                                                
  |========================================                                                                                  |  33%
  |                                                                                                                                
  |==========================================                                                                                |  34%
  |                                                                                                                                
  |============================================                                                                              |  36%
  |                                                                                                                                
  |=============================================                                                                             |  37%
  |                                                                                                                                
  |===============================================                                                                           |  39%
  |                                                                                                                                
  |=================================================                                                                         |  40%
  |                                                                                                                                
  |===================================================                                                                       |  41%
  |                                                                                                                                
  |====================================================                                                                      |  43%
  |                                                                                                                                
  |======================================================                                                                    |  44%
  |                                                                                                                                
  |========================================================                                                                  |  46%
  |                                                                                                                                
  |==========================================================                                                                |  47%
  |                                                                                                                                
  |===========================================================                                                               |  49%
  |                                                                                                                                
  |=============================================================                                                             |  50%
  |                                                                                                                                
  |===============================================================                                                           |  51%
  |                                                                                                                                
  |================================================================                                                          |  53%
  |                                                                                                                                
  |==================================================================                                                        |  54%
  |                                                                                                                                
  |====================================================================                                                      |  56%
  |                                                                                                                                
  |======================================================================                                                    |  57%
  |                                                                                                                                
  |=======================================================================                                                   |  59%
  |                                                                                                                                
  |=========================================================================                                                 |  60%
  |                                                                                                                                
  |===========================================================================                                               |  61%
  |                                                                                                                                
  |=============================================================================                                             |  63%
  |                                                                                                                                
  |==============================================================================                                            |  64%
  |                                                                                                                                
  |================================================================================                                          |  66%
  |                                                                                                                                
  |==================================================================================                                        |  67%
  |                                                                                                                                
  |====================================================================================                                      |  69%
  |                                                                                                                                
  |=====================================================================================                                     |  70%
  |                                                                                                                                
  |=======================================================================================                                   |  71%
  |                                                                                                                                
  |=========================================================================================                                 |  73%
  |                                                                                                                                
  |===========================================================================================                               |  74%
  |                                                                                                                                
  |============================================================================================                              |  76%
  |                                                                                                                                
  |==============================================================================================                            |  77%
  |                                                                                                                                
  |================================================================================================                          |  79%
  |                                                                                                                                
  |==================================================================================================                        |  80%
  |                                                                                                                                
  |===================================================================================================                       |  81%
  |                                                                                                                                
  |=====================================================================================================                     |  83%
  |                                                                                                                                
  |=======================================================================================================                   |  84%
  |                                                                                                                                
  |=========================================================================================================                 |  86%
  |                                                                                                                                
  |==========================================================================================================                |  87%
  |                                                                                                                                
  |============================================================================================================              |  89%
  |                                                                                                                                
  |==============================================================================================================            |  90%
  |                                                                                                                                
  |================================================================================================================          |  91%
  |                                                                                                                                
  |=================================================================================================================         |  93%
  |                                                                                                                                
  |===================================================================================================================       |  94%
  |                                                                                                                                
  |=====================================================================================================================     |  96%
  |                                                                                                                                
  |=======================================================================================================================   |  97%
  |                                                                                                                                
  |========================================================================================================================  |  99%
  |                                                                                                                                
  |==========================================================================================================================| 100%
Computing corrected count matrix for 17667 genes

  |                                                                                                                                
  |                                                                                                                          |   0%
  |                                                                                                                                
  |==                                                                                                                        |   1%
  |                                                                                                                                
  |===                                                                                                                       |   3%
  |                                                                                                                                
  |=====                                                                                                                     |   4%
  |                                                                                                                                
  |=======                                                                                                                   |   6%
  |                                                                                                                                
  |=========                                                                                                                 |   7%
  |                                                                                                                                
  |==========                                                                                                                |   9%
  |                                                                                                                                
  |============                                                                                                              |  10%
  |                                                                                                                                
  |==============                                                                                                            |  11%
  |                                                                                                                                
  |================                                                                                                          |  13%
  |                                                                                                                                
  |=================                                                                                                         |  14%
  |                                                                                                                                
  |===================                                                                                                       |  16%
  |                                                                                                                                
  |=====================                                                                                                     |  17%
  |                                                                                                                                
  |=======================                                                                                                   |  19%
  |                                                                                                                                
  |========================                                                                                                  |  20%
  |                                                                                                                                
  |==========================                                                                                                |  21%
  |                                                                                                                                
  |============================                                                                                              |  23%
  |                                                                                                                                
  |==============================                                                                                            |  24%
  |                                                                                                                                
  |===============================                                                                                           |  26%
  |                                                                                                                                
  |=================================                                                                                         |  27%
  |                                                                                                                                
  |===================================                                                                                       |  29%
  |                                                                                                                                
  |=====================================                                                                                     |  30%
  |                                                                                                                                
  |======================================                                                                                    |  31%
  |                                                                                                                                
  |========================================                                                                                  |  33%
  |                                                                                                                                
  |==========================================                                                                                |  34%
  |                                                                                                                                
  |============================================                                                                              |  36%
  |                                                                                                                                
  |=============================================                                                                             |  37%
  |                                                                                                                                
  |===============================================                                                                           |  39%
  |                                                                                                                                
  |=================================================                                                                         |  40%
  |                                                                                                                                
  |===================================================                                                                       |  41%
  |                                                                                                                                
  |====================================================                                                                      |  43%
  |                                                                                                                                
  |======================================================                                                                    |  44%
  |                                                                                                                                
  |========================================================                                                                  |  46%
  |                                                                                                                                
  |==========================================================                                                                |  47%
  |                                                                                                                                
  |===========================================================                                                               |  49%
  |                                                                                                                                
  |=============================================================                                                             |  50%
  |                                                                                                                                
  |===============================================================                                                           |  51%
  |                                                                                                                                
  |================================================================                                                          |  53%
  |                                                                                                                                
  |==================================================================                                                        |  54%
  |                                                                                                                                
  |====================================================================                                                      |  56%
  |                                                                                                                                
  |======================================================================                                                    |  57%
  |                                                                                                                                
  |=======================================================================                                                   |  59%
  |                                                                                                                                
  |=========================================================================                                                 |  60%
  |                                                                                                                                
  |===========================================================================                                               |  61%
  |                                                                                                                                
  |=============================================================================                                             |  63%
  |                                                                                                                                
  |==============================================================================                                            |  64%
  |                                                                                                                                
  |================================================================================                                          |  66%
  |                                                                                                                                
  |==================================================================================                                        |  67%
  |                                                                                                                                
  |====================================================================================                                      |  69%
  |                                                                                                                                
  |=====================================================================================                                     |  70%
  |                                                                                                                                
  |=======================================================================================                                   |  71%
  |                                                                                                                                
  |=========================================================================================                                 |  73%
  |                                                                                                                                
  |===========================================================================================                               |  74%
  |                                                                                                                                
  |============================================================================================                              |  76%
  |                                                                                                                                
  |==============================================================================================                            |  77%
  |                                                                                                                                
  |================================================================================================                          |  79%
  |                                                                                                                                
  |==================================================================================================                        |  80%
  |                                                                                                                                
  |===================================================================================================                       |  81%
  |                                                                                                                                
  |=====================================================================================================                     |  83%
  |                                                                                                                                
  |=======================================================================================================                   |  84%
  |                                                                                                                                
  |=========================================================================================================                 |  86%
  |                                                                                                                                
  |==========================================================================================================                |  87%
  |                                                                                                                                
  |============================================================================================================              |  89%
  |                                                                                                                                
  |==============================================================================================================            |  90%
  |                                                                                                                                
  |================================================================================================================          |  91%
  |                                                                                                                                
  |=================================================================================================================         |  93%
  |                                                                                                                                
  |===================================================================================================================       |  94%
  |                                                                                                                                
  |=====================================================================================================================     |  96%
  |                                                                                                                                
  |=======================================================================================================================   |  97%
  |                                                                                                                                
  |========================================================================================================================  |  99%
  |                                                                                                                                
  |==========================================================================================================================| 100%
Calculating gene attributes
Wall clock passed: Time difference of 1.46701 mins
Determine variable features
Set 3000 variable features
Place corrected count matrix in counts slot
Centering data matrix

  |                                                                                                                                
  |                                                                                                                          |   0%
  |                                                                                                                                
  |==============================                                                                                            |  25%
  |                                                                                                                                
  |=============================================================                                                             |  50%
  |                                                                                                                                
  |============================================================================================                              |  75%
  |                                                                                                                                
  |==========================================================================================================================| 100%
Set default assay to SCT
SpatialFeaturePlot(mouse_brain_sa, features = c("Hpca", "Ttr"))

From Seurat:

The default parameters in Seurat emphasize the visualization of molecular data. However, you can also adjust the size of the spots (and their transparency) to improve the visualization of the histology image, by changing the following parameters:

pt.size.factor- This will scale the size of the spots. Default is 1.6
alpha - minimum and maximum transparency. Default is c(1, 1).
Try setting to alpha c(0.1, 1), to downweight the transparency of points with lower expression
p1 <- SpatialFeaturePlot(mouse_brain_sa, features = "Ttr", pt.size.factor = 1)+ 
  theme(legend.position = "right") +
  ggtitle("Actual Spot Size")
p2 <- SpatialFeaturePlot(mouse_brain_sa, features = "Ttr", alpha = c(0.1, 1))+ 
  theme(legend.position = "right") +
  ggtitle("Scaled Spot Size")
p1 + p2

Dimensionality reduction, clustering, and visualization

We can then proceed to run dimensionality reduction and clustering on the RNA expression data, using the same workflow as we use for scRNA-seq analysis.

Some of these processes can be parallized

library(future)
# check the current active plan
plan()
sequential:
- args: function (expr, envir = parent.frame(), substitute = TRUE, lazy = FALSE, seed = NULL, globals = TRUE, local = TRUE, earlySignal = FALSE, label = NULL, ...)
- tweaked: FALSE
- call: NULL
# change the current plan to access parallelization
plan("multiprocess", workers = 4)
[ONE-TIME WARNING] Forked processing ('multicore') is disabled in future (>= 1.13.0) when running R from RStudio, because it is considered unstable. Because of this, plan("multicore") will fall back to plan("sequential"), and plan("multiprocess") will fall back to plan("multisession") - not plan("multicore") as in the past. For more details, how to control forked processing or not, and how to silence this warning in future R sessions, see ?future::supportsMulticore
plan()
multiprocess:
- args: function (expr, envir = parent.frame(), substitute = TRUE, lazy = FALSE, seed = NULL, globals = TRUE, workers = 4, gc = FALSE, earlySignal = FALSE, label = NULL, ...)
- tweaked: TRUE
- call: plan("multiprocess", workers = 4)

The defalut UMAP calculation is performed with the R-based UWOT library However, you can run UMAP in python via retuculate library and umap-learn. We have found that for smaller datasets (<= 10k cells/spots) UWOT is great. For much larger datasets (100k +) umap-learn can be a faster option.

mouse_brain_sa <- RunPCA(mouse_brain_sa, assay = "SCT", verbose = FALSE)
mouse_brain_sa <- FindNeighbors(mouse_brain_sa, reduction = "pca", dims = 1:30)
Computing nearest neighbor graph
Computing SNN
mouse_brain_sa <- FindClusters(mouse_brain_sa, verbose = FALSE)
mouse_brain_sa <- RunUMAP(mouse_brain_sa, reduction = "pca", dims = 1:30)
The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
This message will be shown once per session10:55:07 UMAP embedding parameters a = 0.9922 b = 1.112
10:55:07 Read 2696 rows and found 30 numeric columns
10:55:07 Using Annoy for neighbor search, n_neighbors = 30
10:55:07 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
10:55:08 Writing NN index file to temp file /tmp/Rtmpm6Tyoz/file59f2832d4f5bc
10:55:08 Searching Annoy index using 4 threads, search_k = 3000
10:55:08 Annoy recall = 100%
10:55:09 Commencing smooth kNN distance calibration using 4 threads
10:55:09 Initializing from normalized Laplacian + noise
10:55:12 Commencing optimization for 500 epochs, with 105850 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
10:55:19 Optimization finished

Now let’s have a look at the clustering

I don’t really like these colors so let’s change them

p1 <- DimPlot(mouse_brain_sa, reduction = "umap", label = TRUE) +
  labs(color = "Cluster")
p2 <- SpatialDimPlot(mouse_brain_sa, label = TRUE, label.size = 3) +
  labs(fill = "Cluster")
p1 + p2

myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
p1 <- DimPlot(mouse_brain_sa, reduction = "umap", label = TRUE) +
  labs(color = "Cluster") + 
  scale_color_manual(values = c("#b2df8a","#e41a1c","#377eb8","#4daf4a","#ff7f00","gold", 
                               "#a65628", "#999999", "black", "pink", "purple", "brown",
                               "grey", "yellow", "green"))
p2 <- SpatialDimPlot(mouse_brain_sa, label = TRUE, label.size = 3) +
  labs(fill = "Cluster") +
  scale_fill_manual(values = c("#b2df8a","#e41a1c","#377eb8","#4daf4a","#ff7f00","gold", 
                               "#a65628", "#999999", "black", "pink", "purple", "brown",
                               "grey", "yellow", "green"))
p1 + p2 + plot_annotation(
  title = 'Clustering in UMAP and Tissue Space',
  caption = 'Processed by Spaceranger 1.1\nNormilization and Clustering by Seurat'
)

Interactivity not working for me on firefox

Need to upgrade my seurat

SpatialFeaturePlot(mouse_brain_sa, features = "Ttr", do.hover = TRUE)
LinkedDimPlot(mouse_brain_sa)

Spatially variable features

First we’ll idetify differentially expressed genes.

Parallelization helps here too let’s make sure our plan is still intact

plan()
multiprocess:
- args: function (expr, envir = parent.frame(), substitute = TRUE, lazy = FALSE, seed = NULL, globals = TRUE, workers = 4, gc = FALSE, earlySignal = FALSE, label = NULL, ...)
- tweaked: TRUE
- call: plan("multiprocess", workers = 4)

- call: plan("multiprocess", workers = 4) indicates that it is

Looks like we have some very DE genes for clusters 4 and 11

clarify what ident.1 = 4, ident.2 = 6 are for

de_markers <- FindMarkers(mouse_brain_sa, ident.1 = 4, ident.2 = 6)

what are the top variable features?

VariableFeatures(mouse_brain_sa)[1:10]
 [1] "Ttr"     "Plp1"    "Hba-a1"  "Hbb-bs"  "Mbp"     "Penk"    "Ptgds"   "Hba-a2"  "S100a5"  "Ppp1r1b"

what are the top de genes?

rownames(de_markers)[1:10]
 [1] "Calb2"   "Slc6a11" "Ckb"     "Camk2n1" "Doc2g"   "Camk2a"  "Th"      "Nrgn"    "Cdhr1"   "Slc1a2" 

Spatially Variable Genes

So what about spatial enrichment?

Some methods 1. Trendsceek 2. Splotch 3. SPARK 4. SpatialDE + We have found this implimenton not to be very effective. It’s also not under active development

Using the top 100 variable genes find spatially enriched ones. Note that in the Seurat Spatial Tutorial they use 1000 genes. You can also use all genes but that will take a long time. Using a calucation of Morans I can sometimes be a faster approach, especially if you are using parallization.

This step will take ~1 minute.

mouse_brain_sa <- FindSpatiallyVariableFeatures(mouse_brain_sa, assay = "SCT", features = VariableFeatures(mouse_brain_sa)[1:100], 
    selection.method = "markvariogram", verbose = TRUE)

Have a look at the spatially variable genes calculated by markvariogram ordered from most variable to least variable

SpatiallyVariableFeatures(mouse_brain_sa, selection.method = "markvariogram", decreasing = TRUE)
  [1] "Ttr"           "Ppp1r1b"       "Gpr88"         "Penk"          "Pde10a"        "Nrgn"          "Calb2"         "Pde1b"         "S100a5"       
 [10] "Cck"           "Pcp4"          "Gng4"          "Camk2n1"       "Scn4b"         "Mbp"           "Rgs9"          "Doc2g"         "Adcy5"        
 [19] "Fabp7"         "Rasd2"         "Slc17a7"       "Gpsm1"         "Hpca"          "Pcp4l1"        "Olfm1"         "Tac1"          "Snap25"       
 [28] "Cdhr1"         "Mobp"          "Hap1"          "Arpp21"        "Gng7"          "Fth1"          "3110035E14Rik" "Ppp3ca"        "Nptxr"        
 [37] "Synpr"         "Enpp2"         "Adora2a"       "Cpne6"         "Lrrc10b"       "Shisa8"        "Slc6a11"       "Gad1"          "Nnat"         
 [46] "Th"            "Apoe"          "Ptgds"         "Trf"           "Sparc"         "Plp1"          "Cnp"           "Drd2"          "Ptn"          
 [55] "Mal"           "Plekhb1"       "Eomes"         "Agt"           "Qdpr"          "Apod"          "Cryab"         "Mag"           "Gm42418"      
 [64] "Cldn11"        "1500015O10Rik" "Igfbp2"        "Clca3a1"       "Nts"           "Pvalb"         "2900040C04Rik" "Kl"            "Car2"         
 [73] "Gfap"          "Folr1"         "Calml4"        "Trh"           "Mog"           "Tspan2"        "Kcnj13"        "Ctgf"          "Cartpt"       
 [82] "Clic6"         "Myoc"          "Lbp"           "Sst"           "Mgp"           "Kcne2"         "Cplx3"         "Tnnt1"         "Igkc"         
 [91] "Tac2"          "Lars2"         "Npy"           "Hbb-bs"        "Tmem212"       "Vip"           "Hbb-bt"        "Hba-a1"        "Hba-a2"       
[100] "S100a9"       
top.features_trendseq <- head(SpatiallyVariableFeatures(mouse_brain_sa, selection.method = "markvariogram"), 6)
SpatialFeaturePlot(mouse_brain_sa, features = top.features_trendseq, ncol = 3, alpha = c(0.1, 1))
CombinePlots is being deprecated. Plots should now be combined using the patchwork system.

Moran’s I implamentation. For other spatial data types the x.cuts and y.cuts determins the grid that is laied over the tissue in the capture area. Here we’ll remove those

mouse_brain_sa <- FindSpatiallyVariableFeatures(mouse_brain_sa, assay = "SCT", slot = "scale.data", features = VariableFeatures(mouse_brain_sa)[1:100], 
    selection.method = "moransi")
Computing Moran's I

Have a look at the spatially variable genes calculated by moransi ordered from most variable to least variable

SpatiallyVariableFeatures(mouse_brain_sa, selection.method = "moransi", decreasing = TRUE)
  [1] "Calb2"         "Gng4"          "Doc2g"         "Cdhr1"         "Gpsm1"         "Fabp7"         "Nrgn"          "Cck"           "Shisa8"       
 [10] "Ttr"           "Ppp1r1b"       "Gpr88"         "Penk"          "S100a5"        "Th"            "Synpr"         "Hap1"          "Pde10a"       
 [19] "Slc6a11"       "Mbp"           "Camk2n1"       "Pde1b"         "Tac1"          "Adcy5"         "Pcp4l1"        "Slc17a7"       "Scn4b"        
 [28] "Rgs9"          "Gng7"          "3110035E14Rik" "Gad1"          "Rasd2"         "Mobp"          "Olfm1"         "Hpca"          "Cpne6"        
 [37] "Fth1"          "Nts"           "Trf"           "Plp1"          "Enpp2"         "Eomes"         "Arpp21"        "Adora2a"       "Pcp4"         
 [46] "Mal"           "Drd2"          "Lrrc10b"       "Snap25"        "Cnp"           "Ppp3ca"        "Sparc"         "Nnat"          "Agt"          
 [55] "Mag"           "Cldn11"        "Qdpr"          "Nptxr"         "Plekhb1"       "Cryab"         "Pvalb"         "Apoe"          "Mog"          
 [64] "Tspan2"        "Car2"          "Igfbp2"        "Trh"           "Ptn"           "Apod"          "Cartpt"        "1500015O10Rik" "Folr1"        
 [73] "2900040C04Rik" "Sst"           "Kl"            "Clca3a1"       "Gm42418"       "Ptgds"         "Clic6"         "Calml4"        "Gfap"         
 [82] "Kcne2"         "Ctgf"          "Vip"           "Kcnj13"        "Lbp"           "Tmem212"       "Tac2"          "Hbb-bs"        "Igkc"         
 [91] "Lars2"         "Hbb-bt"        "Cplx3"         "Hba-a1"        "Hba-a2"        "Tnnt1"         "Mgp"           "Npy"           "Myoc"         
[100] "S100a9"       
top.features_moransi <- head(SpatiallyVariableFeatures(mouse_brain_sa, selection.method = "moransi"), 8)
SpatialFeaturePlot(mouse_brain_sa, features = top.features_moransi, ncol = 4, alpha = c(0.1, 1))
CombinePlots is being deprecated. Plots should now be combined using the patchwork system.

We can see that the results are slightly different. So let’s take a look at why.

You can see the two methods show

mm_cor <- cor.test(spatially_variable_genes$moransi.spatially.variable.rank, spatially_variable_genes$markvariogram.spatially.variable.rank)
ggplot(spatially_variable_genes, aes(x=moransi.spatially.variable.rank,y=markvariogram.spatially.variable.rank))+
  geom_point()+
  geom_smooth()+
  xlab("Morans I Rank")+
  ylab("Markvariogram Rank")+
  annotate("text", x = 25, y = 75, label = paste("Pearson's Correlation\n", round(mm_cor$estimate[1], digits = 2), sep = ""))+
  theme_bw()

images_cl <- list()

for (i in 1:length(lenas)) {
  images_cl[[i]] <- readbitmap::read.bitmap(paste(get_spatial_path(lenas[i]), "/outs/spatial/tissue_lowres_image.png", sep = ""))
}
height <- list()

for (i in 1:length(lenas)) {
 height[[i]] <-  data.frame(height = nrow(images_cl[[i]]))
}

height <- bind_rows(height)

width <- list()

for (i in 1:length(lenas)) {
 width[[i]] <- data.frame(width = ncol(images_cl[[i]]))
}

width <- bind_rows(width)

###Color from pipeline

grobs <- list()

for (i in 1:length(lenas)) {
  grobs[[i]] <- grid::rasterGrob(images_cl[[i]], width=unit(1,"npc"), height=unit(1,"npc"))
}

images_tibble <- tibble(lena=lenas, grob=grobs)
images_tibble$lena <- factor(images_tibble$lena)
images_tibble$height <- height$height
images_tibble$width <- width$width
images_tibble
scales <- list()

for (i in 1:length(lenas)) {
 path_scales <- paste(svenLib::get_spatial_path(lenas[i]), "/outs/spatial/scalefactors_json.json", sep = "")
 scales[[i]] <- rjson::fromJSON(file = path_scales)
}

Clusters and tsne

clusters <- list()
for (i in 1:length(lenas)) {
  clusters[[i]] <- read.csv(paste(svenLib::get_spatial_path(lenas[i]),"/outs/analysis_csv/clustering/graphclust/clusters.csv", sep = ""))
}


tsne <- list()

for (i in 1:length(lenas)) {
   tsne[[i]] <- read.csv(paste(svenLib::get_spatial_path(lenas[i]),"/outs/analysis_csv/tsne/2_components/projection.csv",sep = ""), header = T)
}

umap <- list()

for (i in 1:length(lenas)) {
   umap[[i]] <- read.csv(paste(svenLib::get_spatial_path(lenas[i]),"/outs/analysis_csv/umap/2_components/projection.csv",sep = ""), header = T)
}

umap[[1]]

Combine clusters, tsne, and tissue info for easy plotting

bcs <- list()

for (i in 1:length(lenas)) {
   if (file.exists(paste(get_spatial_path(lenas[i]),"/outs/spatial/tissue_positions_list.txt", sep = ""))) {
  bcs[[i]] <- read.csv(paste(get_spatial_path(lenas[i]), "/outs/spatial/tissue_positions_list.txt", sep = ""),
                 col.names=c("barcode","tissue","row","col","imagerow","imagecol"), header = F)
        } else {
  bcs[[i]] <- read.csv(paste(get_spatial_path(lenas[i]), "/outs/spatial/tissue_positions_list.csv", sep = ""),
                 col.names=c( "barcode","tissue","row","col","imagerow","imagecol"), header = F)
        }
   bcs[[i]]$imagerow_scaled <- bcs[[i]]$imagerow * scales[[i]]$tissue_lowres_scalef    # scale tissue coordinates for lowres image
   bcs[[i]]$imagecol_scaled <- bcs[[i]]$imagecol * scales[[i]]$tissue_lowres_scalef
   bcs[[i]]$imagerow_scaled_round <- round(bcs[[i]]$imagerow * scales[[i]]$tissue_lowres_scalef) # Rounded scales
   bcs[[i]]$imagecol_scaled_round <- round(bcs[[i]]$imagecol * scales[[i]]$tissue_lowres_scalef)
   bcs[[i]]$tissue <- as.factor(bcs[[i]]$tissue)
   bcs[[i]] <- merge(bcs[[i]], clusters[[i]], by.x = "barcode", by.y = "Barcode", all = TRUE)
   bcs[[i]] <- merge(bcs[[i]], tsne[[i]], by.x = "barcode", by.y = "Barcode", all = TRUE)
   bcs[[i]] <- merge(bcs[[i]], umap[[i]], by.x = "barcode", by.y = "Barcode", all = TRUE)
   bcs[[i]]$height <- height$height[i]
   bcs[[i]]$width <- width$width[i]
}

names(bcs) <- lenas
read_matrix <- function(sid) {
  Matrix::t(Seurat::Read10X_h5(paste(get_spatial_path(sid = sid), "/outs/raw_feature_bc_matrix.h5", sep = "")))
}

matrix <- map(.x = lenas, .f = read_matrix)
names(matrix) <- lenas
matrix[[1]]
umi_sum <- list() 

for (i in 1:length(lenas)) {
  umi_sum[[i]] <- data.frame(barcode =  row.names(matrix[[i]]),
                             sum_umi = Matrix::rowSums(matrix[[i]]))
  
}
names(umi_sum) <- lenas

umi_sum <- bind_rows(umi_sum, .id = "lena")
umi_sum


gene_sum <- list() 

for (i in 1:length(lenas)) {
  gene_sum[[i]] <- data.frame(barcode =  row.names(matrix[[i]]),
                             sum_gene = Matrix::rowSums(matrix[[i]] != 0))
  
}
names(gene_sum) <- lenas

gene_sum <- bind_rows(gene_sum, .id = "lena")
gene_sum

# If you need to look at the correlation of gene expression between samples
gene_umi_sum <- list() 

for (i in 1:length(lenas)) {
  gene_umi_sum[[i]] <- data.frame(gene =  colnames(matrix[[i]]),
                             gene_umi_sum = Matrix::colSums(matrix[[i]]))
  
}
names(gene_umi_sum) <- lenas

gene_umi_sum <- bind_rows(gene_umi_sum, .id = "lena")
gene_umi_sum
bcs_merge <- bind_rows(bcs, .id = "lena")
bcs_merge <- merge(bcs_merge,umi_sum, by = c("barcode", "lena"))
bcs_merge <- merge(bcs_merge,gene_sum, by = c("barcode", "lena"))

Define our color palette for plotting

myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
plots <- list()

for (i in 1:length(lenas)) {

plots[[i]] <- bcs_merge %>% 
  filter(lena ==lenas[i]) %>% 
  filter(tissue =="1") %>% 
      ggplot(aes(x=imagecol_scaled,y=imagerow_scaled,fill=sum_umi)) +
                geom_spatial(data=images_tibble[i,], aes(grob=grob), x=0.5, y=0.5)+
                geom_point(shape = 21, colour = "black", size = 2, stroke = 0.1)+
                coord_cartesian(expand=FALSE)+
                scale_fill_gradientn(colours = myPalette(100))+
                #facet_wrap(~lena)+
                xlim(0,max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(width)))+
                ylim(max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(height)),0)+
                xlab("") +
                ylab("") +
                ggtitle(paste(lenas[i],": ", sample_type[i], sep = ""))+
                labs(fill = "UMI")+
                theme_set(theme_bw(base_size = 10))+
                theme(panel.grid.major = element_blank(), 
                        panel.grid.minor = element_blank(),
                        panel.background = element_blank(), 
                        axis.line = element_line(colour = "black"),
                        axis.text = element_blank())
}

patchwork::wrap_plots(plots)
plots <- list()

for (i in 1:length(lenas)) {

plots[[i]] <- bcs_merge %>% 
  filter(lena ==lenas[i]) %>% 
  filter(tissue =="1") %>% 
      ggplot(aes(x=imagecol_scaled,y=imagerow_scaled,fill=sum_gene)) +
                geom_spatial(data=images_tibble[i,], aes(grob=grob), x=0.5, y=0.5)+
                geom_point(shape = 21, colour = "black", size = 2, stroke = 0.1)+
                coord_cartesian(expand=FALSE)+
                scale_fill_gradientn(colours = myPalette(100))+
                #facet_wrap(~lena)+
                xlim(0,max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(width)))+
                ylim(max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(height)),0)+
                xlab("") +
                ylab("") +
                ggtitle(paste(lenas[i],": ", sample_type[i], sep = ""))+
                labs(fill = "Genes")+
                theme_set(theme_bw(base_size = 10))+
                theme(panel.grid.major = element_blank(), 
                        panel.grid.minor = element_blank(),
                        panel.background = element_blank(), 
                        axis.line = element_line(colour = "black"),
                        axis.text = element_blank())
}

patchwork::wrap_plots(plots)
plots <- list()

for (i in 1:length(lenas)) {

plots[[i]] <- bcs_merge %>% 
  filter(lena ==lenas[i]) %>%
  add_column(GAPDH = matrix[[i]][,"GAPDH"]) %>% 
      ggplot(aes(x=imagecol_scaled,y=imagerow_scaled,fill=GAPDH)) +
                geom_spatial(data=images_tibble[i,], aes(grob=grob), x=0.5, y=0.5)+
                geom_point(shape = 21, colour = "black", size = 2, stroke = 0.1)+
                coord_cartesian(expand=FALSE)+
                scale_fill_gradientn(colours = myPalette(100))+
                #facet_wrap(~lena)+
                xlim(0,max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(width)))+
                ylim(max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(height)),0)+
                xlab("") +
                ylab("") +
                ggtitle(paste(lenas[i],": ", sample_type[i], sep = ""))+
                labs(fill = "GAPDH UMI")+
                theme_set(theme_bw(base_size = 10))+
                theme(panel.grid.major = element_blank(), 
                        panel.grid.minor = element_blank(),
                        panel.background = element_blank(), 
                        axis.line = element_line(colour = "black"),
                        axis.text = element_blank())
}

patchwork::wrap_plots(plots)
plots <- list()

for (i in 1:length(lenas)) {

plots[[i]] <- bcs_merge %>% 
  filter(lena ==lenas[i]) %>%
  filter(tissue == "1") %>% 
  na.omit() %>% 
      ggplot(aes(x=imagecol_scaled,y=imagerow_scaled,fill=factor(Cluster))) +
                geom_spatial(data=images_tibble[i,], aes(grob=grob), x=0.5, y=0.5)+
                geom_point(shape = 21, colour = "black", size = 2, stroke = 0.1)+
                coord_cartesian(expand=FALSE)+
                scale_fill_manual(values = c("#b2df8a","#e41a1c","#377eb8","#4daf4a","#ff7f00","gold", 
                                             "#a65628", "#999999", "black", "white", "purple", "brown"))+
                xlim(0,max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(width)))+
                ylim(max(bcs_merge %>% 
                            filter(lena ==lenas[i]) %>% 
                            dplyr::select(height)),0)+
                xlab("") +
                ylab("") +
                ggtitle(paste(lenas[i],": ", sample_type[i], sep = ""))+
                labs(fill = "Cluster")+
                guides(fill = guide_legend(override.aes = list(size=3)))+
                theme_set(theme_bw(base_size = 10))+
                theme(panel.grid.major = element_blank(), 
                        panel.grid.minor = element_blank(),
                        panel.background = element_blank(), 
                        axis.line = element_line(colour = "black"),
                        axis.text = element_blank())
  
}
patchwork::wrap_plots(plots)
LS0tCnRpdGxlOiAiU0lCIERheXMgMjAyMCAtIFZpcnR1YWwgQ29uZmVyZW5jZSIKYXV0aG9yOgogIC0gUGF0cmljayBSb2VsbGksIENvbXB1dGF0aW9uYWwgQmlvbG9naXN0IDIgLSBDb21wdXRhdGlvbmFsIEJpb2xvZ3leWzEweCBHZW5vbWljcywgcGF0cmljay5yb2VsbGlAMTB4Z2Vub21pY3MuY29tIF0KICAtIFN0ZWZhbmlhIEdpYWNvbWVsbG8sIENvbXB1dGF0aW9uYWwgQmlvbG9naXN0IDIgLSBDb21wdXRhdGlvbmFsIEJpb2xvZ3leWzEweCBHZW5vbWljcywgc3RlcGhlbi53aWxsaWFtc0AxMHhnZW5vbWljcy5jb21dCiAgLSBTdGVwaGVuIFdpbGxpYW1zLCBTZW5pb3IgU2NpZW50aXN0IC0gQ29tcHV0YXRpb25hbCBCaW9sb2d5XlsxMHggR2Vub21pY3MsIHN0ZXBoZW4ud2lsbGlhbXNAMTB4Z2Vub21pY3MuY29tXQpkYXRlOiAnQ29tcGlsZWQ6IGByIGZvcm1hdChTeXMuRGF0ZSgpLCAiJUIgJWQsICVZIilgJwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogbm9uZQogICAgdGhlbWU6IGpvdXJuYWwKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogeWVzCi0tLQoKIyAqKkludHJvZHVjdGlvbioqCgpXZWxjb21lIHRvIHRoZSAqKlNJQiBEYXlzIDIwMjAgLSB2aXJ0dWFsIGNvbmZlcmVuY2UqKiBTcGF0aWFsIFRyYW5zY3JpcHRvbWljcyB3b3Jrc2hvcCBieSAxMHggZ2Vub21pY3MhCgpbIVsxMHggSG9tZV0oaHR0cHM6Ly9naXRodWIuY29tL3N0ZXBoZW53aWxsaWFtczIyL1NJQl8yMDIwX1dvcmtzaG9wL3Jhdy9tYXN0ZXIvaW1hZ2VzLzEweCUyMGhvbWVwYWdlLnBuZyldKGh0dHBzOi8vd3d3LjEweGdlbm9taWNzLmNvbS8pCgoKVGhlIHB1cnBvc2Ugb2YgdGhpcyB0dXRvcmlhbCB3aWxsIGJlIHRvIHdhbGsgdXNlcnMgdGhyb3VnaCBzb21lIG9mIHRoZSBzdGVwcyBuZWNlc3NhcnkgdG8gZXhwbG9yZSBkYXRhIHByb2R1Y2VkIGJ5IHRoZSAxMHggR2Vub21pY3MgVmlzaXVtIFNwYXRhaWwgR2VuZSBFeHByZXNzaW9uIFNvbHV0aW9uIGFuZCB0aGUgW1NwYWNlcmFuZ2VyIHBpcGVsaW5lXShodHRwczovL3N1cHBvcnQuMTB4Z2Vub21pY3MuY29tL3NwYXRpYWwtZ2VuZS1leHByZXNzaW9uL3NvZnR3YXJlL3BpcGVsaW5lcy9sYXRlc3Qvd2hhdC1pcy1zcGFjZS1yYW5nZXIpLiBXZSB3aWxsIGludmVzdGlnYXRlIHRoZSBkYXRhc2V0cyB3aGl0aCBhcmUgYWxsIGZyZWVseSBhdmFpbGFibGUgZnJvbSBbMTB4IEdlbm9taWNzXShodHRwczovL3N1cHBvcnQuMTB4Z2Vub21pY3MuY29tL3NwYXRpYWwtZ2VuZS1leHByZXNzaW9uL2RhdGFzZXRzKS4KCltTZXVyYXQgVHV0b3JpYWxdKGh0dHBzOi8vc2F0aWphbGFiLm9yZy9zZXVyYXQvdjMuMS9zcGF0aWFsX3ZpZ25ldHRlLmh0bWwpCgoqKlRoaW5ncyB0byBrbm93IGFib3V0IHRoaXMgd29ya3Nob3AqKgoKMS4gQWxsIGZpbGVzIHRoYXQgd2lsbCBiZSB1c2VkIGNhbiBiZSBmb3VuZCBhdDogYC9tbnQvbGlicy9zaGFyZWRfZGF0YS9gCjIuIEdldHRpbmcgc3RhcnRlZCB3aXRoIFIgYW5kIFZpc2l1bSBkYXRhIG91dHNpZGUgb2YgU2V1cmF0IGF0OiBodHRwczovL3N1cHBvcnQuMTB4Z2Vub21pY3MuY29tL3NwYXRpYWwtZ2VuZS1leHByZXNzaW9uL3NvZnR3YXJlL3BpcGVsaW5lcy9sYXRlc3QvcmtpdAozLiBSZWZlcmVuY2UgZ2Vub21lIGZvciBhbGwgc2FtcGxlcyBpcyBHUkNoMzgvbW0xMAo0LiBBbGwgMTB4IHNvZnR3YXJlIGluY2x1ZGluZyBbU3BhY2VyYW5nZXJdKGh0dHBzOi8vc3VwcG9ydC4xMHhnZW5vbWljcy5jb20vc3BhdGlhbC1nZW5lLWV4cHJlc3Npb24vc29mdHdhcmUvcGlwZWxpbmVzL2xhdGVzdC93aGF0LWlzLXNwYWNlLXJhbmdlciksIGFuZCBbTG91cGUgQnJvd3Nlcl0oaHR0cHM6Ly9zdXBwb3J0LjEweGdlbm9taWNzLmNvbS9zcGF0aWFsLWdlbmUtZXhwcmVzc2lvbi9zb2Z0d2FyZS92aXN1YWxpemF0aW9uL2xhdGVzdC93aGF0LWlzLWxvdXBlLWJyb3dzZXIpLCBjYW4gYmUgZG93bmxvYWRlZCBmcm9tIHRoZSBbMTB4IFN1cHBvcnQgU2l0ZV0oaHR0cHM6Ly9zdXBwb3J0LjEweGdlbm9taWNzLmNvbS8pIAoKCiMgKipFeHBsb3JpbmcgVmlzaXVtIERhdGEgd2l0aCBTZXVyYXQqKgojIyBMb2FkIG91ciBwYWNrYWdlcwpgYGB7ciBMaWJyYXJpZXMsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpgYGAKCiMjIExvYWRpbmcgZGF0YSBpbiBhIFNldXJhdCBvYmplY3QKClJlYWwgRGF0YXNldCBmb3IgdGhlIHR1dG9yaWFsCmBgYHtyIGV2YWw9RkFMU0V9Cm1vdXNlX2JyYWluX3NhIDwtIExvYWQxMFhfU3BhdGlhbChkYXRhLmRpciA9ICIvbW50L2xpYnMvc2hhcmVkX2RhdGEvbW91c2VfYnJhaW5fc2Evb3V0cy8iLAogICAgICAgICAgICAgICAgZmlsZW5hbWUgPSAiVjFfTW91c2VfQnJhaW5fU2FnaXR0YWxfQW50ZXJpb3JfZmlsdGVyZWRfZmVhdHVyZV9iY19tYXRyaXguaDUiKQpgYGAKCgpTYW1lIGRhdGEganVzdCBpbnRlcm5hbCB0byAxMHgKYGBge3J9Cm1vdXNlX2JyYWluX3NhIDwtIExvYWQxMFhfU3BhdGlhbChkYXRhLmRpciA9ICIvbW50L2FuYWx5c2lzL21hcnNvYy9waXBlc3RhbmNlcy9ITUtMRkRNWFgvU1BBVElBTF9STkFfQ09VTlRFUl9QRC8xNjAxMjEvSEVBRC9vdXRzLyIpCmBgYAoKVGhlcmUgYXJlIGEgYnVuY2ggb2YgZGF0YXNldHMgaG90ZWQgYnkgdGhlIFNhdGlqYSBsYWIgaW4gdGhlIFtTZXVyYXQgRGF0YSBQYWNrYWdlXShodHRwczovL2dpdGh1Yi5jb20vc2F0aWphbGFiL3NldXJhdC1kYXRhKS4KCiMgUmVzdWx0cwojIyBRQwpMZXQncyBoYXZlIGEgbG9vayBhdCBzb21lIGJhc2ljIFFDIGluZm9ybWF0aW9uLiBLZWVwIGluIG1pbmQgdGhhdCBtb3N0IHNldXJhdCBwbG90cyBhcmUgZ2dwbG90IG9iamVjdCBhbmQgY2FuIGJlIG1hbmlwdWxhdGVkIGFzIHN1Y2guCgpDb3VudHMgPSBVTUkKRmVhdHVyZXMgPSBHZW5lcwpgYGB7ciwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpwbG90MSA8LSBWbG5QbG90KG1vdXNlX2JyYWluX3NhLCBmZWF0dXJlcyA9ICJuQ291bnRfU3BhdGlhbCIsIHB0LnNpemUgPSAwLjEpICsgCiAgZ2d0aXRsZSgiVU1JIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsKICBOb0xlZ2VuZCgpCgpwbG90MiA8LSBWbG5QbG90KG1vdXNlX2JyYWluX3NhLCBmZWF0dXJlcyA9ICJuRmVhdHVyZV9TcGF0aWFsIiwgcHQuc2l6ZSA9IDAuMSkgKyAKICBnZ3RpdGxlKCJHZW5lcyIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSArCiAgTm9MZWdlbmQoKQoKcGxvdDMgPC0gU3BhdGlhbEZlYXR1cmVQbG90KG1vdXNlX2JyYWluX3NhLCBmZWF0dXJlcyA9ICJuQ291bnRfU3BhdGlhbCIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCnBsb3Q0IDwtIFNwYXRpYWxGZWF0dXJlUGxvdChtb3VzZV9icmFpbl9zYSwgZmVhdHVyZXMgPSAibkZlYXR1cmVfU3BhdGlhbCIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKcGxvdDEgKyBwbG90MiArIHBsb3QzICsgcGxvdDQgKyBwbG90X2xheW91dChucm93ID0gMiwgbmNvbCA9IDIpCmBgYAoKIyMgTm9ybWlsaXphdGlvbgoKU3BhY2VyYW5nZXIgZG9lcyBub3JtaWxpYXp0aW9uIGZvciBjbHVzdGVyaW5nIGFuZCBERSBidXQgZG9lcyBub3QgcmV0dXJuIHRoYXQgbm9ybWFsaXplZCBtYXRyaXgKClByZS1ub3JtYWxpemF0aW9uIApSYXcgVU1JIGNvdW50cwpgYGB7ciwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpTcGF0aWFsRmVhdHVyZVBsb3QobW91c2VfYnJhaW5fc2EsIGZlYXR1cmVzID0gYygiSHBjYSIsICJUdHIiKSkKYGBgClNFIHRyYW5zZm9ybQoKRG9uJ3Qgd29ycnkgYWJvdXQgYHJlYWNoZWRpdGVyYXRpb24gbGltaXRgIHdhcm5pbmdzLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL0NocmlzdG9waEgvc2N0cmFuc2Zvcm0vaXNzdWVzLzI1IGZvciBkaXNjdXNzaW9uCgpEZWZhdWx0IGFzc2F5IHdpbGwgbm93IGJlIHNldCB0byBTQ1QKYGBge3J9Cm1vdXNlX2JyYWluX3NhIDwtIFNDVHJhbnNmb3JtKG1vdXNlX2JyYWluX3NhLCBhc3NheSA9ICJTcGF0aWFsIiwgdmVyYm9zZSA9IFRSVUUpCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xMCwgd2FybmluZz1GQUxTRX0KU3BhdGlhbEZlYXR1cmVQbG90KG1vdXNlX2JyYWluX3NhLCBmZWF0dXJlcyA9IGMoIkhwY2EiLCAiVHRyIikpCmBgYAoKCkZyb20gU2V1cmF0OiAKClRoZSBkZWZhdWx0IHBhcmFtZXRlcnMgaW4gU2V1cmF0IGVtcGhhc2l6ZSB0aGUgdmlzdWFsaXphdGlvbiBvZiBtb2xlY3VsYXIgZGF0YS4gSG93ZXZlciwgeW91IGNhbiBhbHNvIGFkanVzdCB0aGUgc2l6ZSBvZiB0aGUgc3BvdHMgKGFuZCB0aGVpciB0cmFuc3BhcmVuY3kpIHRvIGltcHJvdmUgdGhlIHZpc3VhbGl6YXRpb24gb2YgdGhlIGhpc3RvbG9neSBpbWFnZSwgYnkgY2hhbmdpbmcgdGhlIGZvbGxvd2luZyBwYXJhbWV0ZXJzOgoKICAgIHB0LnNpemUuZmFjdG9yLSBUaGlzIHdpbGwgc2NhbGUgdGhlIHNpemUgb2YgdGhlIHNwb3RzLiBEZWZhdWx0IGlzIDEuNgogICAgYWxwaGEgLSBtaW5pbXVtIGFuZCBtYXhpbXVtIHRyYW5zcGFyZW5jeS4gRGVmYXVsdCBpcyBjKDEsIDEpLgogICAgVHJ5IHNldHRpbmcgdG8gYWxwaGEgYygwLjEsIDEpLCB0byBkb3dud2VpZ2h0IHRoZSB0cmFuc3BhcmVuY3kgb2YgcG9pbnRzIHdpdGggbG93ZXIgZXhwcmVzc2lvbgoKCgpgYGB7ciwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpwMSA8LSBTcGF0aWFsRmVhdHVyZVBsb3QobW91c2VfYnJhaW5fc2EsIGZlYXR1cmVzID0gIlR0ciIsIHB0LnNpemUuZmFjdG9yID0gMSkrIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsKICBnZ3RpdGxlKCJBY3R1YWwgU3BvdCBTaXplIikKcDIgPC0gU3BhdGlhbEZlYXR1cmVQbG90KG1vdXNlX2JyYWluX3NhLCBmZWF0dXJlcyA9ICJUdHIiLCBhbHBoYSA9IGMoMC4xLCAxKSkrIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsKICBnZ3RpdGxlKCJTY2FsZWQgU3BvdCBTaXplIikKcDEgKyBwMgpgYGAKCkRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiwgY2x1c3RlcmluZywgYW5kIHZpc3VhbGl6YXRpb24KCldlIGNhbiB0aGVuIHByb2NlZWQgdG8gcnVuIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiBhbmQgY2x1c3RlcmluZyBvbiB0aGUgUk5BIGV4cHJlc3Npb24gZGF0YSwgdXNpbmcgdGhlIHNhbWUgd29ya2Zsb3cgYXMgd2UgdXNlIGZvciBzY1JOQS1zZXEgYW5hbHlzaXMuCgpTb21lIG9mIHRoZXNlIHByb2Nlc3NlcyBjYW4gYmUgcGFyYWxsaXplZAoKYGBge3J9CmxpYnJhcnkoZnV0dXJlKQojIGNoZWNrIHRoZSBjdXJyZW50IGFjdGl2ZSBwbGFuCnBsYW4oKQpgYGAKYGBge3J9CiMgY2hhbmdlIHRoZSBjdXJyZW50IHBsYW4gdG8gYWNjZXNzIHBhcmFsbGVsaXphdGlvbgpwbGFuKCJtdWx0aXByb2Nlc3MiLCB3b3JrZXJzID0gNCkKcGxhbigpCmBgYAoKClRoZSBkZWZhbHV0IFVNQVAgY2FsY3VsYXRpb24gaXMgcGVyZm9ybWVkIHdpdGggdGhlIFtSLWJhc2VkIFVXT1RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy91d290L2luZGV4Lmh0bWwpIGxpYnJhcnkgSG93ZXZlciwgeW91IGNhbiBydW4gVU1BUCBpbiBweXRob24gdmlhIHJldHVjdWxhdGUgbGlicmFyeSBhbmQgYHVtYXAtbGVhcm5gLiBXZSBoYXZlIGZvdW5kIHRoYXQgZm9yIHNtYWxsZXIgZGF0YXNldHMgKDw9IDEwayBjZWxscy9zcG90cykgVVdPVCBpcyBncmVhdC4gRm9yIG11Y2ggbGFyZ2VyIGRhdGFzZXRzICgxMDBrICspIGB1bWFwLWxlYXJuYCBjYW4gYmUgYSBmYXN0ZXIgb3B0aW9uLiAKYGBge3J9Cm1vdXNlX2JyYWluX3NhIDwtIFJ1blBDQShtb3VzZV9icmFpbl9zYSwgYXNzYXkgPSAiU0NUIiwgdmVyYm9zZSA9IEZBTFNFKQptb3VzZV9icmFpbl9zYSA8LSBGaW5kTmVpZ2hib3JzKG1vdXNlX2JyYWluX3NhLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MzApCm1vdXNlX2JyYWluX3NhIDwtIEZpbmRDbHVzdGVycyhtb3VzZV9icmFpbl9zYSwgdmVyYm9zZSA9IEZBTFNFKQptb3VzZV9icmFpbl9zYSA8LSBSdW5VTUFQKG1vdXNlX2JyYWluX3NhLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MzApCmBgYAoKTm93IGxldCdzIGhhdmUgYSBsb29rIGF0IHRoZSBjbHVzdGVyaW5nCgpJIGRvbid0IHJlYWxseSBsaWtlIHRoZXNlIGNvbG9ycyBzbyBsZXQncyBjaGFuZ2UgdGhlbQpgYGB7ciwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpwMSA8LSBEaW1QbG90KG1vdXNlX2JyYWluX3NhLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSkgKwogIGxhYnMoY29sb3IgPSAiQ2x1c3RlciIpCnAyIDwtIFNwYXRpYWxEaW1QbG90KG1vdXNlX2JyYWluX3NhLCBsYWJlbCA9IFRSVUUsIGxhYmVsLnNpemUgPSAzKSArCiAgbGFicyhmaWxsID0gIkNsdXN0ZXIiKQpwMSArIHAyCmBgYApgYGB7cn0KbXlQYWxldHRlIDwtIGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwoMTEsICJTcGVjdHJhbCIpKSkKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpwMSA8LSBEaW1QbG90KG1vdXNlX2JyYWluX3NhLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSkgKwogIGxhYnMoY29sb3IgPSAiQ2x1c3RlciIpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiNiMmRmOGEiLCIjZTQxYTFjIiwiIzM3N2ViOCIsIiM0ZGFmNGEiLCIjZmY3ZjAwIiwiZ29sZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiNhNjU2MjgiLCAiIzk5OTk5OSIsICJibGFjayIsICJwaW5rIiwgInB1cnBsZSIsICJicm93biIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3JleSIsICJ5ZWxsb3ciLCAiZ3JlZW4iKSkKcDIgPC0gU3BhdGlhbERpbVBsb3QobW91c2VfYnJhaW5fc2EsIGxhYmVsID0gVFJVRSwgbGFiZWwuc2l6ZSA9IDMpICsKICBsYWJzKGZpbGwgPSAiQ2x1c3RlciIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjYjJkZjhhIiwiI2U0MWExYyIsIiMzNzdlYjgiLCIjNGRhZjRhIiwiI2ZmN2YwMCIsImdvbGQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIjYTY1NjI4IiwgIiM5OTk5OTkiLCAiYmxhY2siLCAicGluayIsICJwdXJwbGUiLCAiYnJvd24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImdyZXkiLCAieWVsbG93IiwgImdyZWVuIikpCnAxICsgcDIgKyBwbG90X2Fubm90YXRpb24oCiAgdGl0bGUgPSAnQ2x1c3RlcmluZyBpbiBVTUFQIGFuZCBUaXNzdWUgU3BhY2UnLAogIGNhcHRpb24gPSAnUHJvY2Vzc2VkIGJ5IFNwYWNlcmFuZ2VyIDEuMVxuTm9ybWlsaXphdGlvbiBhbmQgQ2x1c3RlcmluZyBieSBTZXVyYXQnCikKYGBgCgpJbnRlcmFjdGl2aXR5IG5vdCB3b3JraW5nIGZvciBtZSBvbiBmaXJlZm94CgpOZWVkIHRvIHVwZ3JhZGUgbXkgc2V1cmF0CmBgYHtyfQpTcGF0aWFsRmVhdHVyZVBsb3QobW91c2VfYnJhaW5fc2EsIGZlYXR1cmVzID0gIlR0ciIsIGRvLmhvdmVyID0gVFJVRSkKYGBgCgpgYGB7cn0KTGlua2VkRGltUGxvdChtb3VzZV9icmFpbl9zYSkKYGBgCgojIyBTcGF0aWFsbHkgdmFyaWFibGUgZmVhdHVyZXMKCkZpcnN0IHdlJ2xsIGlkZXRpZnkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzLiAKClBhcmFsbGVsaXphdGlvbiBoZWxwcyBoZXJlIHRvbyBsZXQncyBtYWtlIHN1cmUgb3VyIHBsYW4gaXMgc3RpbGwgaW50YWN0CgpgYGB7cn0KcGxhbigpCmBgYApgLSBjYWxsOiBwbGFuKCJtdWx0aXByb2Nlc3MiLCB3b3JrZXJzID0gNClgIGluZGljYXRlcyB0aGF0IGl0IGlzCgpMb29rcyBsaWtlIHdlIGhhdmUgc29tZSB2ZXJ5IERFIGdlbmVzIGZvciBjbHVzdGVycyA0IGFuZCAxMQoKCmNsYXJpZnkgd2hhdCBpZGVudC4xID0gNCwgaWRlbnQuMiA9IDYgYXJlIGZvcgpgYGB7ciwgZmlnLndpZHRoPTEwLCB3YXJuaW5nPUZBTFNFfQpkZV9tYXJrZXJzIDwtIEZpbmRNYXJrZXJzKG1vdXNlX2JyYWluX3NhLCBpZGVudC4xID0gNCwgaWRlbnQuMiA9IDYpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTAsIHdhcm5pbmc9RkFMU0V9CnAxIDwtIFNwYXRpYWxGZWF0dXJlUGxvdChvYmplY3QgPSBtb3VzZV9icmFpbl9zYSwgZmVhdHVyZXMgPSByb3duYW1lcyhkZV9tYXJrZXJzKVsxOjNdLCBhbHBoYSA9IGMoMC4xLCAxKSwgbmNvbCA9IDMpCnAyIDwtIFNwYXRpYWxEaW1QbG90KG1vdXNlX2JyYWluX3NhLCBsYWJlbCA9IFRSVUUsIGxhYmVsLnNpemUgPSAzKSArCiAgbGFicyhmaWxsID0gIkNsdXN0ZXIiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2IyZGY4YSIsIiNlNDFhMWMiLCIjMzc3ZWI4IiwiIzRkYWY0YSIsIiNmZjdmMDAiLCJnb2xkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiI2E2NTYyOCIsICIjOTk5OTk5IiwgImJsYWNrIiwgInBpbmsiLCAicHVycGxlIiwgImJyb3duIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJncmV5IiwgInllbGxvdyIsICJncmVlbiIpKQpwMSArIHAyICsgIHBsb3RfbGF5b3V0KG5jb2wgID0gMSwgd2lkdGhzID0gYygxLCAxKSkKYGBgCndoYXQgYXJlIHRoZSB0b3AgdmFyaWFibGUgZmVhdHVyZXM/CmBgYHtyfQpWYXJpYWJsZUZlYXR1cmVzKG1vdXNlX2JyYWluX3NhKVsxOjEwXQpgYGAKCndoYXQgYXJlIHRoZSB0b3AgZGUgZ2VuZXM/CmBgYHtyfQpyb3duYW1lcyhkZV9tYXJrZXJzKVsxOjEwXQpgYGAKCiMjIFNwYXRpYWxseSBWYXJpYWJsZSBHZW5lcwoKU28gd2hhdCBhYm91dCBzcGF0aWFsIGVucmljaG1lbnQ/IAoKU29tZSBtZXRob2RzCjEuIFtUcmVuZHNjZWVrXShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25tZXRoLjQ2MzQpCjIuIFtTcGxvdGNoXShodHRwczovL3d3dy5iaW9yeGl2Lm9yZy9jb250ZW50LzEwLjExMDEvNzU3MDk2djEpCjMuIFtTUEFSS10oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9zNDE1OTItMDE5LTA3MDEtNykKNC4gW1NwYXRpYWxERV0oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9ubWV0aC40NjM2KQogICsgV2UgaGF2ZSBmb3VuZCB0aGlzIGltcGxpbWVudG9uIG5vdCB0byBiZSB2ZXJ5IGVmZmVjdGl2ZS4gSXQncyBhbHNvIG5vdCB1bmRlciBhY3RpdmUgZGV2ZWxvcG1lbnQKCgpVc2luZyB0aGUgdG9wIDEwMCB2YXJpYWJsZSBnZW5lcyBmaW5kIHNwYXRpYWxseSBlbnJpY2hlZCBvbmVzLiBOb3RlIHRoYXQgaW4gdGhlIFNldXJhdCBTcGF0aWFsIFR1dG9yaWFsIHRoZXkgdXNlIDEwMDAgZ2VuZXMuIFlvdSBjYW4gYWxzbyB1c2UgYWxsIGdlbmVzIGJ1dCB0aGF0IHdpbGwgdGFrZSBhIGxvbmcgdGltZS4gVXNpbmcgYSBjYWx1Y2F0aW9uIG9mIFtNb3JhbnMgSV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTW9yYW4lMjdzX0kpIGNhbiBzb21ldGltZXMgYmUgYSBmYXN0ZXIgYXBwcm9hY2gsIGVzcGVjaWFsbHkgaWYgeW91IGFyZSB1c2luZyBwYXJhbGxpemF0aW9uLgoKVGhpcyBzdGVwIHdpbGwgdGFrZSB+MSBtaW51dGUuCgpgYGB7cn0KbW91c2VfYnJhaW5fc2EgPC0gRmluZFNwYXRpYWxseVZhcmlhYmxlRmVhdHVyZXMobW91c2VfYnJhaW5fc2EsIGFzc2F5ID0gIlNDVCIsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhtb3VzZV9icmFpbl9zYSlbMToxMDBdLCAKICAgIHNlbGVjdGlvbi5tZXRob2QgPSAibWFya3ZhcmlvZ3JhbSIsIHZlcmJvc2UgPSBUUlVFKQpgYGAKCkhhdmUgYSBsb29rIGF0IHRoZSBzcGF0aWFsbHkgdmFyaWFibGUgZ2VuZXMgY2FsY3VsYXRlZCBieSBgbWFya3ZhcmlvZ3JhbWAgb3JkZXJlZCBmcm9tIG1vc3QgdmFyaWFibGUgdG8gbGVhc3QgdmFyaWFibGUKYGBge3J9ClNwYXRpYWxseVZhcmlhYmxlRmVhdHVyZXMobW91c2VfYnJhaW5fc2EsIHNlbGVjdGlvbi5tZXRob2QgPSAibWFya3ZhcmlvZ3JhbSIsIGRlY3JlYXNpbmcgPSBUUlVFKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9OH0KdG9wLmZlYXR1cmVzX3RyZW5kc2VxIDwtIGhlYWQoU3BhdGlhbGx5VmFyaWFibGVGZWF0dXJlcyhtb3VzZV9icmFpbl9zYSwgc2VsZWN0aW9uLm1ldGhvZCA9ICJtYXJrdmFyaW9ncmFtIiksIDYpClNwYXRpYWxGZWF0dXJlUGxvdChtb3VzZV9icmFpbl9zYSwgZmVhdHVyZXMgPSB0b3AuZmVhdHVyZXNfdHJlbmRzZXEsIG5jb2wgPSAzLCBhbHBoYSA9IGMoMC4xLCAxKSkKYGBgCgpNb3JhbidzIEkgaW1wbGFtZW50YXRpb24uIEZvciBvdGhlciBzcGF0aWFsIGRhdGEgdHlwZXMgdGhlIHguY3V0cyBhbmQgeS5jdXRzIGRldGVybWlucyB0aGUgZ3JpZCB0aGF0IGlzIGxhaWVkIG92ZXIgdGhlIHRpc3N1ZSBpbiB0aGUgY2FwdHVyZSBhcmVhLiBIZXJlIHdlJ2xsIHJlbW92ZSB0aG9zZQpgYGB7cn0KbW91c2VfYnJhaW5fc2EgPC0gRmluZFNwYXRpYWxseVZhcmlhYmxlRmVhdHVyZXMobW91c2VfYnJhaW5fc2EsIGFzc2F5ID0gIlNDVCIsIHNsb3QgPSAic2NhbGUuZGF0YSIsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhtb3VzZV9icmFpbl9zYSlbMToxMDBdLCAKICAgIHNlbGVjdGlvbi5tZXRob2QgPSAibW9yYW5zaSIpCmBgYAoKCkhhdmUgYSBsb29rIGF0IHRoZSBzcGF0aWFsbHkgdmFyaWFibGUgZ2VuZXMgY2FsY3VsYXRlZCBieSBgbW9yYW5zaWAgb3JkZXJlZCBmcm9tIG1vc3QgdmFyaWFibGUgdG8gbGVhc3QgdmFyaWFibGUKCmBgYHtyfQpTcGF0aWFsbHlWYXJpYWJsZUZlYXR1cmVzKG1vdXNlX2JyYWluX3NhLCBzZWxlY3Rpb24ubWV0aG9kID0gIm1vcmFuc2kiLCBkZWNyZWFzaW5nID0gVFJVRSkKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9CnRvcC5mZWF0dXJlc19tb3JhbnNpIDwtIGhlYWQoU3BhdGlhbGx5VmFyaWFibGVGZWF0dXJlcyhtb3VzZV9icmFpbl9zYSwgc2VsZWN0aW9uLm1ldGhvZCA9ICJtb3JhbnNpIiksIDgpClNwYXRpYWxGZWF0dXJlUGxvdChtb3VzZV9icmFpbl9zYSwgZmVhdHVyZXMgPSB0b3AuZmVhdHVyZXNfbW9yYW5zaSwgbmNvbCA9IDQsIGFscGhhID0gYygwLjEsIDEpKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgcmVzdWx0cyBhcmUgc2xpZ2h0bHkgZGlmZmVyZW50LiBTbyBsZXQncyB0YWtlIGEgbG9vayBhdCB3aHkuCgpgYGB7cn0Kc3BhdGlhbGx5X3ZhcmlhYmxlX2dlbmVzIDwtIG1vdXNlX2JyYWluX3NhQGFzc2F5cyRTQ1RAbWV0YS5mZWF0dXJlcyAlPiUKICB0aWR5cjo6ZHJvcF9uYSgpCgpzcGF0aWFsbHlfdmFyaWFibGVfZ2VuZXMKYGBgCllvdSBjYW4gc2VlIHRoZSB0d28gbWV0aG9kcyBzaG93IApgYGB7cn0KbW1fY29yIDwtIGNvci50ZXN0KHNwYXRpYWxseV92YXJpYWJsZV9nZW5lcyRtb3JhbnNpLnNwYXRpYWxseS52YXJpYWJsZS5yYW5rLCBzcGF0aWFsbHlfdmFyaWFibGVfZ2VuZXMkbWFya3ZhcmlvZ3JhbS5zcGF0aWFsbHkudmFyaWFibGUucmFuaykKZ2dwbG90KHNwYXRpYWxseV92YXJpYWJsZV9nZW5lcywgYWVzKHg9bW9yYW5zaS5zcGF0aWFsbHkudmFyaWFibGUucmFuayx5PW1hcmt2YXJpb2dyYW0uc3BhdGlhbGx5LnZhcmlhYmxlLnJhbmspKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9zbW9vdGgoKSsKICB4bGFiKCJNb3JhbnMgSSBSYW5rIikrCiAgeWxhYigiTWFya3ZhcmlvZ3JhbSBSYW5rIikrCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMjUsIHkgPSA3NSwgbGFiZWwgPSBwYXN0ZSgiUGVhcnNvbidzIENvcnJlbGF0aW9uXG4iLCByb3VuZChtbV9jb3IkZXN0aW1hdGVbMV0sIGRpZ2l0cyA9IDIpLCBzZXAgPSAiIikpKwogIHRoZW1lX2J3KCkKYGBgCgoKCmBgYHtyfQppbWFnZXNfY2wgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiAgaW1hZ2VzX2NsW1tpXV0gPC0gcmVhZGJpdG1hcDo6cmVhZC5iaXRtYXAocGFzdGUoZ2V0X3NwYXRpYWxfcGF0aChsZW5hc1tpXSksICIvb3V0cy9zcGF0aWFsL3Rpc3N1ZV9sb3dyZXNfaW1hZ2UucG5nIiwgc2VwID0gIiIpKQp9CmBgYAoKCmBgYHtyfQpoZWlnaHQgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiBoZWlnaHRbW2ldXSA8LSAgZGF0YS5mcmFtZShoZWlnaHQgPSBucm93KGltYWdlc19jbFtbaV1dKSkKfQoKaGVpZ2h0IDwtIGJpbmRfcm93cyhoZWlnaHQpCgp3aWR0aCA8LSBsaXN0KCkKCmZvciAoaSBpbiAxOmxlbmd0aChsZW5hcykpIHsKIHdpZHRoW1tpXV0gPC0gZGF0YS5mcmFtZSh3aWR0aCA9IG5jb2woaW1hZ2VzX2NsW1tpXV0pKQp9Cgp3aWR0aCA8LSBiaW5kX3Jvd3Mod2lkdGgpCmBgYAoKCiMjI0NvbG9yIGZyb20gcGlwZWxpbmUKYGBge3J9Cmdyb2JzIDwtIGxpc3QoKQoKZm9yIChpIGluIDE6bGVuZ3RoKGxlbmFzKSkgewogIGdyb2JzW1tpXV0gPC0gZ3JpZDo6cmFzdGVyR3JvYihpbWFnZXNfY2xbW2ldXSwgd2lkdGg9dW5pdCgxLCJucGMiKSwgaGVpZ2h0PXVuaXQoMSwibnBjIikpCn0KCmltYWdlc190aWJibGUgPC0gdGliYmxlKGxlbmE9bGVuYXMsIGdyb2I9Z3JvYnMpCmltYWdlc190aWJibGUkbGVuYSA8LSBmYWN0b3IoaW1hZ2VzX3RpYmJsZSRsZW5hKQppbWFnZXNfdGliYmxlJGhlaWdodCA8LSBoZWlnaHQkaGVpZ2h0CmltYWdlc190aWJibGUkd2lkdGggPC0gd2lkdGgkd2lkdGgKaW1hZ2VzX3RpYmJsZQpgYGAKCmBgYHtyfQpzY2FsZXMgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiBwYXRoX3NjYWxlcyA8LSBwYXN0ZShzdmVuTGliOjpnZXRfc3BhdGlhbF9wYXRoKGxlbmFzW2ldKSwgIi9vdXRzL3NwYXRpYWwvc2NhbGVmYWN0b3JzX2pzb24uanNvbiIsIHNlcCA9ICIiKQogc2NhbGVzW1tpXV0gPC0gcmpzb246OmZyb21KU09OKGZpbGUgPSBwYXRoX3NjYWxlcykKfQpgYGAKCiMjIyBDbHVzdGVycyBhbmQgdHNuZQpgYGB7cn0KY2x1c3RlcnMgPC0gbGlzdCgpCmZvciAoaSBpbiAxOmxlbmd0aChsZW5hcykpIHsKICBjbHVzdGVyc1tbaV1dIDwtIHJlYWQuY3N2KHBhc3RlKHN2ZW5MaWI6OmdldF9zcGF0aWFsX3BhdGgobGVuYXNbaV0pLCIvb3V0cy9hbmFseXNpc19jc3YvY2x1c3RlcmluZy9ncmFwaGNsdXN0L2NsdXN0ZXJzLmNzdiIsIHNlcCA9ICIiKSkKfQoKCnRzbmUgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiAgIHRzbmVbW2ldXSA8LSByZWFkLmNzdihwYXN0ZShzdmVuTGliOjpnZXRfc3BhdGlhbF9wYXRoKGxlbmFzW2ldKSwiL291dHMvYW5hbHlzaXNfY3N2L3RzbmUvMl9jb21wb25lbnRzL3Byb2plY3Rpb24uY3N2IixzZXAgPSAiIiksIGhlYWRlciA9IFQpCn0KCnVtYXAgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiAgIHVtYXBbW2ldXSA8LSByZWFkLmNzdihwYXN0ZShzdmVuTGliOjpnZXRfc3BhdGlhbF9wYXRoKGxlbmFzW2ldKSwiL291dHMvYW5hbHlzaXNfY3N2L3VtYXAvMl9jb21wb25lbnRzL3Byb2plY3Rpb24uY3N2IixzZXAgPSAiIiksIGhlYWRlciA9IFQpCn0KCnVtYXBbWzFdXQpgYGAKCgojIyMgQ29tYmluZSBjbHVzdGVycywgdHNuZSwgYW5kIHRpc3N1ZSBpbmZvIGZvciBlYXN5IHBsb3R0aW5nCmBgYHtyfQpiY3MgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiAgIGlmIChmaWxlLmV4aXN0cyhwYXN0ZShnZXRfc3BhdGlhbF9wYXRoKGxlbmFzW2ldKSwiL291dHMvc3BhdGlhbC90aXNzdWVfcG9zaXRpb25zX2xpc3QudHh0Iiwgc2VwID0gIiIpKSkgewogIGJjc1tbaV1dIDwtIHJlYWQuY3N2KHBhc3RlKGdldF9zcGF0aWFsX3BhdGgobGVuYXNbaV0pLCAiL291dHMvc3BhdGlhbC90aXNzdWVfcG9zaXRpb25zX2xpc3QudHh0Iiwgc2VwID0gIiIpLAogICAgICAgICAgICAgICAgIGNvbC5uYW1lcz1jKCJiYXJjb2RlIiwidGlzc3VlIiwicm93IiwiY29sIiwiaW1hZ2Vyb3ciLCJpbWFnZWNvbCIpLCBoZWFkZXIgPSBGKQogICAgICAgIH0gZWxzZSB7CiAgYmNzW1tpXV0gPC0gcmVhZC5jc3YocGFzdGUoZ2V0X3NwYXRpYWxfcGF0aChsZW5hc1tpXSksICIvb3V0cy9zcGF0aWFsL3Rpc3N1ZV9wb3NpdGlvbnNfbGlzdC5jc3YiLCBzZXAgPSAiIiksCiAgICAgICAgICAgICAgICAgY29sLm5hbWVzPWMoICJiYXJjb2RlIiwidGlzc3VlIiwicm93IiwiY29sIiwiaW1hZ2Vyb3ciLCJpbWFnZWNvbCIpLCBoZWFkZXIgPSBGKQogICAgICAgIH0KICAgYmNzW1tpXV0kaW1hZ2Vyb3dfc2NhbGVkIDwtIGJjc1tbaV1dJGltYWdlcm93ICogc2NhbGVzW1tpXV0kdGlzc3VlX2xvd3Jlc19zY2FsZWYgICAgIyBzY2FsZSB0aXNzdWUgY29vcmRpbmF0ZXMgZm9yIGxvd3JlcyBpbWFnZQogICBiY3NbW2ldXSRpbWFnZWNvbF9zY2FsZWQgPC0gYmNzW1tpXV0kaW1hZ2Vjb2wgKiBzY2FsZXNbW2ldXSR0aXNzdWVfbG93cmVzX3NjYWxlZgogICBiY3NbW2ldXSRpbWFnZXJvd19zY2FsZWRfcm91bmQgPC0gcm91bmQoYmNzW1tpXV0kaW1hZ2Vyb3cgKiBzY2FsZXNbW2ldXSR0aXNzdWVfbG93cmVzX3NjYWxlZikgIyBSb3VuZGVkIHNjYWxlcwogICBiY3NbW2ldXSRpbWFnZWNvbF9zY2FsZWRfcm91bmQgPC0gcm91bmQoYmNzW1tpXV0kaW1hZ2Vjb2wgKiBzY2FsZXNbW2ldXSR0aXNzdWVfbG93cmVzX3NjYWxlZikKICAgYmNzW1tpXV0kdGlzc3VlIDwtIGFzLmZhY3RvcihiY3NbW2ldXSR0aXNzdWUpCiAgIGJjc1tbaV1dIDwtIG1lcmdlKGJjc1tbaV1dLCBjbHVzdGVyc1tbaV1dLCBieS54ID0gImJhcmNvZGUiLCBieS55ID0gIkJhcmNvZGUiLCBhbGwgPSBUUlVFKQogICBiY3NbW2ldXSA8LSBtZXJnZShiY3NbW2ldXSwgdHNuZVtbaV1dLCBieS54ID0gImJhcmNvZGUiLCBieS55ID0gIkJhcmNvZGUiLCBhbGwgPSBUUlVFKQogICBiY3NbW2ldXSA8LSBtZXJnZShiY3NbW2ldXSwgdW1hcFtbaV1dLCBieS54ID0gImJhcmNvZGUiLCBieS55ID0gIkJhcmNvZGUiLCBhbGwgPSBUUlVFKQogICBiY3NbW2ldXSRoZWlnaHQgPC0gaGVpZ2h0JGhlaWdodFtpXQogICBiY3NbW2ldXSR3aWR0aCA8LSB3aWR0aCR3aWR0aFtpXQp9CgpuYW1lcyhiY3MpIDwtIGxlbmFzCmBgYAoKCmBgYHtyfQpyZWFkX21hdHJpeCA8LSBmdW5jdGlvbihzaWQpIHsKICBNYXRyaXg6OnQoU2V1cmF0OjpSZWFkMTBYX2g1KHBhc3RlKGdldF9zcGF0aWFsX3BhdGgoc2lkID0gc2lkKSwgIi9vdXRzL3Jhd19mZWF0dXJlX2JjX21hdHJpeC5oNSIsIHNlcCA9ICIiKSkpCn0KCm1hdHJpeCA8LSBtYXAoLnggPSBsZW5hcywgLmYgPSByZWFkX21hdHJpeCkKbmFtZXMobWF0cml4KSA8LSBsZW5hcwptYXRyaXhbWzFdXQpgYGAKCgpgYGB7cn0KdW1pX3N1bSA8LSBsaXN0KCkgCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiAgdW1pX3N1bVtbaV1dIDwtIGRhdGEuZnJhbWUoYmFyY29kZSA9ICByb3cubmFtZXMobWF0cml4W1tpXV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bV91bWkgPSBNYXRyaXg6OnJvd1N1bXMobWF0cml4W1tpXV0pKQogIAp9Cm5hbWVzKHVtaV9zdW0pIDwtIGxlbmFzCgp1bWlfc3VtIDwtIGJpbmRfcm93cyh1bWlfc3VtLCAuaWQgPSAibGVuYSIpCnVtaV9zdW0KCgpnZW5lX3N1bSA8LSBsaXN0KCkgCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiAgZ2VuZV9zdW1bW2ldXSA8LSBkYXRhLmZyYW1lKGJhcmNvZGUgPSAgcm93Lm5hbWVzKG1hdHJpeFtbaV1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1fZ2VuZSA9IE1hdHJpeDo6cm93U3VtcyhtYXRyaXhbW2ldXSAhPSAwKSkKICAKfQpuYW1lcyhnZW5lX3N1bSkgPC0gbGVuYXMKCmdlbmVfc3VtIDwtIGJpbmRfcm93cyhnZW5lX3N1bSwgLmlkID0gImxlbmEiKQpnZW5lX3N1bQoKIyBJZiB5b3UgbmVlZCB0byBsb29rIGF0IHRoZSBjb3JyZWxhdGlvbiBvZiBnZW5lIGV4cHJlc3Npb24gYmV0d2VlbiBzYW1wbGVzCmdlbmVfdW1pX3N1bSA8LSBsaXN0KCkgCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CiAgZ2VuZV91bWlfc3VtW1tpXV0gPC0gZGF0YS5mcmFtZShnZW5lID0gIGNvbG5hbWVzKG1hdHJpeFtbaV1dKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX3VtaV9zdW0gPSBNYXRyaXg6OmNvbFN1bXMobWF0cml4W1tpXV0pKQogIAp9Cm5hbWVzKGdlbmVfdW1pX3N1bSkgPC0gbGVuYXMKCmdlbmVfdW1pX3N1bSA8LSBiaW5kX3Jvd3MoZ2VuZV91bWlfc3VtLCAuaWQgPSAibGVuYSIpCmdlbmVfdW1pX3N1bQpgYGAKCmBgYHtyfQpiY3NfbWVyZ2UgPC0gYmluZF9yb3dzKGJjcywgLmlkID0gImxlbmEiKQpiY3NfbWVyZ2UgPC0gbWVyZ2UoYmNzX21lcmdlLHVtaV9zdW0sIGJ5ID0gYygiYmFyY29kZSIsICJsZW5hIikpCmJjc19tZXJnZSA8LSBtZXJnZShiY3NfbWVyZ2UsZ2VuZV9zdW0sIGJ5ID0gYygiYmFyY29kZSIsICJsZW5hIikpCmBgYAoKRGVmaW5lIG91ciBjb2xvciBwYWxldHRlIGZvciBwbG90dGluZwpgYGB7cn0KbXlQYWxldHRlIDwtIGNvbG9yUmFtcFBhbGV0dGUocmV2KGJyZXdlci5wYWwoMTEsICJTcGVjdHJhbCIpKSkKYGBgCgpgYGB7ciwgZmlnLndpZHRoID0gMTgsIGZpZy5oZWlnaHQgPSA5fQpwbG90cyA8LSBsaXN0KCkKCmZvciAoaSBpbiAxOmxlbmd0aChsZW5hcykpIHsKCnBsb3RzW1tpXV0gPC0gYmNzX21lcmdlICU+JSAKICBmaWx0ZXIobGVuYSA9PWxlbmFzW2ldKSAlPiUgCiAgZmlsdGVyKHRpc3N1ZSA9PSIxIikgJT4lIAogICAgICBnZ3Bsb3QoYWVzKHg9aW1hZ2Vjb2xfc2NhbGVkLHk9aW1hZ2Vyb3dfc2NhbGVkLGZpbGw9c3VtX3VtaSkpICsKICAgICAgICAgICAgICAgIGdlb21fc3BhdGlhbChkYXRhPWltYWdlc190aWJibGVbaSxdLCBhZXMoZ3JvYj1ncm9iKSwgeD0wLjUsIHk9MC41KSsKICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDIsIHN0cm9rZSA9IDAuMSkrCiAgICAgICAgICAgICAgICBjb29yZF9jYXJ0ZXNpYW4oZXhwYW5kPUZBTFNFKSsKICAgICAgICAgICAgICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnMgPSBteVBhbGV0dGUoMTAwKSkrCiAgICAgICAgICAgICAgICAjZmFjZXRfd3JhcCh+bGVuYSkrCiAgICAgICAgICAgICAgICB4bGltKDAsbWF4KGJjc19tZXJnZSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIobGVuYSA9PWxlbmFzW2ldKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KHdpZHRoKSkpKwogICAgICAgICAgICAgICAgeWxpbShtYXgoYmNzX21lcmdlICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihsZW5hID09bGVuYXNbaV0pICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoaGVpZ2h0KSksMCkrCiAgICAgICAgICAgICAgICB4bGFiKCIiKSArCiAgICAgICAgICAgICAgICB5bGFiKCIiKSArCiAgICAgICAgICAgICAgICBnZ3RpdGxlKHBhc3RlKGxlbmFzW2ldLCI6ICIsIHNhbXBsZV90eXBlW2ldLCBzZXAgPSAiIikpKwogICAgICAgICAgICAgICAgbGFicyhmaWxsID0gIlVNSSIpKwogICAgICAgICAgICAgICAgdGhlbWVfc2V0KHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwKSkrCiAgICAgICAgICAgICAgICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpKQp9CgpwYXRjaHdvcms6OndyYXBfcGxvdHMocGxvdHMpCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDE4LCBmaWcuaGVpZ2h0ID0gOX0KcGxvdHMgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CgpwbG90c1tbaV1dIDwtIGJjc19tZXJnZSAlPiUgCiAgZmlsdGVyKGxlbmEgPT1sZW5hc1tpXSkgJT4lIAogIGZpbHRlcih0aXNzdWUgPT0iMSIpICU+JSAKICAgICAgZ2dwbG90KGFlcyh4PWltYWdlY29sX3NjYWxlZCx5PWltYWdlcm93X3NjYWxlZCxmaWxsPXN1bV9nZW5lKSkgKwogICAgICAgICAgICAgICAgZ2VvbV9zcGF0aWFsKGRhdGE9aW1hZ2VzX3RpYmJsZVtpLF0sIGFlcyhncm9iPWdyb2IpLCB4PTAuNSwgeT0wLjUpKwogICAgICAgICAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMiwgc3Ryb2tlID0gMC4xKSsKICAgICAgICAgICAgICAgIGNvb3JkX2NhcnRlc2lhbihleHBhbmQ9RkFMU0UpKwogICAgICAgICAgICAgICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IG15UGFsZXR0ZSgxMDApKSsKICAgICAgICAgICAgICAgICNmYWNldF93cmFwKH5sZW5hKSsKICAgICAgICAgICAgICAgIHhsaW0oMCxtYXgoYmNzX21lcmdlICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihsZW5hID09bGVuYXNbaV0pICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3Qod2lkdGgpKSkrCiAgICAgICAgICAgICAgICB5bGltKG1heChiY3NfbWVyZ2UgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKGxlbmEgPT1sZW5hc1tpXSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChoZWlnaHQpKSwwKSsKICAgICAgICAgICAgICAgIHhsYWIoIiIpICsKICAgICAgICAgICAgICAgIHlsYWIoIiIpICsKICAgICAgICAgICAgICAgIGdndGl0bGUocGFzdGUobGVuYXNbaV0sIjogIiwgc2FtcGxlX3R5cGVbaV0sIHNlcCA9ICIiKSkrCiAgICAgICAgICAgICAgICBsYWJzKGZpbGwgPSAiR2VuZXMiKSsKICAgICAgICAgICAgICAgIHRoZW1lX3NldCh0aGVtZV9idyhiYXNlX3NpemUgPSAxMCkpKwogICAgICAgICAgICAgICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgICAgICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkKfQoKcGF0Y2h3b3JrOjp3cmFwX3Bsb3RzKHBsb3RzKQpgYGAKCmBgYHtyLCBmaWcud2lkdGggPSAxOCwgZmlnLmhlaWdodCA9IDl9CnBsb3RzIDwtIGxpc3QoKQoKZm9yIChpIGluIDE6bGVuZ3RoKGxlbmFzKSkgewoKcGxvdHNbW2ldXSA8LSBiY3NfbWVyZ2UgJT4lIAogIGZpbHRlcihsZW5hID09bGVuYXNbaV0pICU+JQogIGFkZF9jb2x1bW4oR0FQREggPSBtYXRyaXhbW2ldXVssIkdBUERIIl0pICU+JSAKICAgICAgZ2dwbG90KGFlcyh4PWltYWdlY29sX3NjYWxlZCx5PWltYWdlcm93X3NjYWxlZCxmaWxsPUdBUERIKSkgKwogICAgICAgICAgICAgICAgZ2VvbV9zcGF0aWFsKGRhdGE9aW1hZ2VzX3RpYmJsZVtpLF0sIGFlcyhncm9iPWdyb2IpLCB4PTAuNSwgeT0wLjUpKwogICAgICAgICAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMiwgc3Ryb2tlID0gMC4xKSsKICAgICAgICAgICAgICAgIGNvb3JkX2NhcnRlc2lhbihleHBhbmQ9RkFMU0UpKwogICAgICAgICAgICAgICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IG15UGFsZXR0ZSgxMDApKSsKICAgICAgICAgICAgICAgICNmYWNldF93cmFwKH5sZW5hKSsKICAgICAgICAgICAgICAgIHhsaW0oMCxtYXgoYmNzX21lcmdlICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihsZW5hID09bGVuYXNbaV0pICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3Qod2lkdGgpKSkrCiAgICAgICAgICAgICAgICB5bGltKG1heChiY3NfbWVyZ2UgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKGxlbmEgPT1sZW5hc1tpXSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChoZWlnaHQpKSwwKSsKICAgICAgICAgICAgICAgIHhsYWIoIiIpICsKICAgICAgICAgICAgICAgIHlsYWIoIiIpICsKICAgICAgICAgICAgICAgIGdndGl0bGUocGFzdGUobGVuYXNbaV0sIjogIiwgc2FtcGxlX3R5cGVbaV0sIHNlcCA9ICIiKSkrCiAgICAgICAgICAgICAgICBsYWJzKGZpbGwgPSAiR0FQREggVU1JIikrCiAgICAgICAgICAgICAgICB0aGVtZV9zZXQodGhlbWVfYncoYmFzZV9zaXplID0gMTApKSsKICAgICAgICAgICAgICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpLAogICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpCn0KCnBhdGNod29yazo6d3JhcF9wbG90cyhwbG90cykKYGBgCgoKYGBge3IsIGZpZy53aWR0aCA9IDE4LCBmaWcuaGVpZ2h0ID0gOX0KcGxvdHMgPC0gbGlzdCgpCgpmb3IgKGkgaW4gMTpsZW5ndGgobGVuYXMpKSB7CgpwbG90c1tbaV1dIDwtIGJjc19tZXJnZSAlPiUgCiAgZmlsdGVyKGxlbmEgPT1sZW5hc1tpXSkgJT4lCiAgZmlsdGVyKHRpc3N1ZSA9PSAiMSIpICU+JSAKICBuYS5vbWl0KCkgJT4lIAogICAgICBnZ3Bsb3QoYWVzKHg9aW1hZ2Vjb2xfc2NhbGVkLHk9aW1hZ2Vyb3dfc2NhbGVkLGZpbGw9ZmFjdG9yKENsdXN0ZXIpKSkgKwogICAgICAgICAgICAgICAgZ2VvbV9zcGF0aWFsKGRhdGE9aW1hZ2VzX3RpYmJsZVtpLF0sIGFlcyhncm9iPWdyb2IpLCB4PTAuNSwgeT0wLjUpKwogICAgICAgICAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMiwgc3Ryb2tlID0gMC4xKSsKICAgICAgICAgICAgICAgIGNvb3JkX2NhcnRlc2lhbihleHBhbmQ9RkFMU0UpKwogICAgICAgICAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2IyZGY4YSIsIiNlNDFhMWMiLCIjMzc3ZWI4IiwiIzRkYWY0YSIsIiNmZjdmMDAiLCJnb2xkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIjYTY1NjI4IiwgIiM5OTk5OTkiLCAiYmxhY2siLCAid2hpdGUiLCAicHVycGxlIiwgImJyb3duIikpKwogICAgICAgICAgICAgICAgeGxpbSgwLG1heChiY3NfbWVyZ2UgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKGxlbmEgPT1sZW5hc1tpXSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdCh3aWR0aCkpKSsKICAgICAgICAgICAgICAgIHlsaW0obWF4KGJjc19tZXJnZSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIobGVuYSA9PWxlbmFzW2ldKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KGhlaWdodCkpLDApKwogICAgICAgICAgICAgICAgeGxhYigiIikgKwogICAgICAgICAgICAgICAgeWxhYigiIikgKwogICAgICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShsZW5hc1tpXSwiOiAiLCBzYW1wbGVfdHlwZVtpXSwgc2VwID0gIiIpKSsKICAgICAgICAgICAgICAgIGxhYnMoZmlsbCA9ICJDbHVzdGVyIikrCiAgICAgICAgICAgICAgICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9MykpKSsKICAgICAgICAgICAgICAgIHRoZW1lX3NldCh0aGVtZV9idyhiYXNlX3NpemUgPSAxMCkpKwogICAgICAgICAgICAgICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgICAgICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkKICAKfQpwYXRjaHdvcms6OndyYXBfcGxvdHMocGxvdHMpCmBgYAoKCg==